/*
Copyright (c) [2019年5月1日] [吴超]
[MBT_Studio] is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
		 http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
*/
#include "stdafx.h"
#include "矩阵节点.h"

#include "节点/节点树.h"
#include "节点/插座/通用插座.h"
#include "节点/插座/list/list数值插座.h"
#include "节点/插座/list/list物体插座.h"
#include "节点/插座/list/list矢量插座.h"


#include "节点/socket_utils.h"
#include "Context/数据创建销毁.h"





C_矩阵变换节点::C_矩阵变换节点(S_设备环境& ctx) : C_节点基类("矩阵变换节点") {
	f_setWName(u"矩阵变换");
	m_Ctx = ctx;

	C_插座基类* socket;
	DEF_创建Vec3_1D插座_I(u"矢量");
	DEF_创建Mat4X4_1D插座_I(u"矩阵");
	
	DEF_创建Vec3_1D插座_O(u"变换后矢量");


	/*m_计算方式 = f_alloc_EnumProp(
		//	0				1				2				3				4
		{
			{u"*", ""}, {u"逆矩阵", ""}, {u"直接相乘", ""},
			//	5			6			7				8			9			10
			//{u"+=", ""}, {u"-=", ""}, {u"*=", ""}, {u"/=", ""}, {u"%=", ""}, {u"点积", ""},
		},
		u"计算方式",
		0,
		nullptr
	);
	m_计算方式.m_私有 = true;*/

	m_是否改变原数据 = f_alloc_BoolProp(nullptr, u"是否改变原数据");
	m_是否改变原数据.m_私有 = true;

	m_执行代码 = f_alloc_BoolProp(nullptr, u"执行代码");
	m_执行代码.m_私有 = true;

}

C_矩阵变换节点::~C_矩阵变换节点() {

}

bool C_矩阵变换节点::f_update() {
	const auto* inVec = DEF_Vec3插座_1D数据(f_get输入插座(1), 0);
	const auto* inMat = DEF_Mat44插座_1D数据(f_get输入插座(2), 0);
	
	auto* outVec = DEF_Vec3插座_1D数据(f_get输出插座(1), 0);


	f_math_mat44_变换m(inVec, inMat, outVec);

	return false;
}

void C_矩阵变换节点::f_读取(FILE* f) {
	C_节点基类::f_读取(f);
	auto 文件块 = f_file_读取文件块(f);

	if (文件块.m_块类型 == E_节点工程文件块类型::e_工程文件块_节点实例属性) {
		const uint8* 下一次读取数据指针 = 文件块.m_data;
		下一次读取数据指针 = f_prop_Load(m_是否改变原数据, 下一次读取数据指针);
		下一次读取数据指针 = f_prop_Load(m_执行代码, 下一次读取数据指针);
	}
	free(文件块.m_data);
}

void C_矩阵变换节点::f_写入(FILE* f) {
	C_节点基类::f_写入(f);
	auto 文件块 = f_文件块_创建(E_节点工程文件块类型::e_工程文件块_节点实例属性, S_引擎配置::g_文件版本号);

	S_UI8Array* 块 = (S_UI8Array*)f_core_array_new(0, sizeof(uint8));
	f_prop_Save(m_是否改变原数据, 块);
	f_prop_Save(m_执行代码, 块);

	f_file_保存文件块(f, 文件块, 块);
}

std::string C_矩阵变换节点::f_编译(C_节点基类* rn, std::string& 声明, std::vector<std::string>& 定义, std::string& 释放) {
	m_Code = "";
	m_ReleaseCode = "";


	C_插座基类* socket0 = f_get输入插座(1);
	
	std::string 新变量 = f_getName();

	//兼容C++端口数据
	if (socket0->m_Type == E_值类型::e_Type_Vec3_Array1D) {
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 1, E_值类型::e_Type_Vec3_1D);
		socket0 = f_get输入插座(1);
	}

	switch (socket0->m_Type) {
	case E_值类型::e_Type_Vec3:
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 2, E_值类型::e_Type_Mat4X4);
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 1, E_值类型::e_Type_Vec3);
		m_Code = "vec3 " + 新变量 + ";\n";
		break;
	case E_值类型::e_Type_Vec3_Array1D:
	case E_值类型::e_Type_Vec3_1D: {
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 2, E_值类型::e_Type_Mat4X4_1D);
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 1, E_值类型::e_Type_Vec3_1D);
		m_Code = "S_Vec3Array* " + 新变量 + ";\n";
		break;
	}
	default:
		return "";
	}

	C_插座基类* socket1 = f_get输入插座(2);


	m_Code += "{\n";

	m_Code += socket0->f_构建变量代码(0);
	m_Code += socket1->f_构建变量代码(0);


	switch (socket0->m_Type) {
	case E_值类型::e_Type_Vec3:
		m_Code += 新变量 + " = " + socket1->f_getCode(0) + " * " + socket0->f_getCode(0) + ";\n";
		break;
	case E_值类型::e_Type_Vec3_1D:
		m_Code += 新变量 + " = " + f_代码构建_创建Array(E_值类型::e_Type_Vec3_1D, "1");
		m_Code += DEF_S(f_math_mat44_变换m)"(" + socket0->f_getCode(0) + ", " + socket1->f_getCode(0) + ", " + 新变量 + "); \n";
		break;
	}

	m_Code += m_ReleaseCode;
	m_Code += "}\n";


	f_get输出插座(1)->f_setCode(新变量);
	if (m_区域父节点) {
		m_区域父节点->m_Code += m_Code;
		m_区域父节点->m_ReleaseCode += f_代码构建_销毁数组(新变量);
		return "";
	}
	释放+= f_代码构建_销毁数组(新变量);
	
	return m_Code;
}

void C_矩阵变换节点::f_物体变换(S_物体* ob, const vec3& loc, const vec3& rot, const vec3& scal, uint32 offset) {
	ob->f_set位置(loc, offset);
	ob->f_set旋转(rot, offset);
	ob->f_set缩放(scal, offset);
}

void C_矩阵变换节点::f_网格变换(S_Mesh* ob, const vec3& loc, const vec3& rot, const vec3& scal, uint32 offset) {
	f_surface_变换(ob, { loc , rot , scal });
	return;
}

void C_矩阵变换节点::f_坐标变换(vec3& outData, const vec3& loc, const vec3& rot, const vec3& scal, uint32 offset) {
	C_Mat44 mat = C_Mat44::kIdentity;

	auto rx = f_构建旋转矩阵(rot.x, E_轴向::e_X);
	auto ry = f_构建旋转矩阵(rot.y, E_轴向::e_Y);
	auto rz = f_构建旋转矩阵(rot.z, E_轴向::e_Z);

	auto s = f_构建缩放矩阵(scal);

	mat *= f_构建移动矩阵(loc);

	mat *= rz;
	mat *= ry;
	mat *= rx;
	mat *= s;

	outData = mat * outData;

}


C_节点基类* f_node_创建矩阵变换节点(S_设备环境& ctx, C_节点树* 子节点树) {
	return new C_矩阵变换节点(ctx);
}

C_节点基类* f_node_加载矩阵变换节点(S_设备环境& ctx, FILE* f) {
	C_矩阵变换节点* node = new C_矩阵变换节点(ctx);
	//fread(&(((S_PropValueEnum*)node->m_成员.m_Value)->m_当前选项), sizeof(uint8), 1, f);
	return node;
}

void f_node_保存矩阵变换节点(C_节点基类* n, FILE* f) {
	C_矩阵变换节点* node = dynamic_cast<C_矩阵变换节点*>(n);
	//fwrite(&(((S_PropValueEnum*)node->m_成员.m_Value)->m_当前选项), sizeof(uint8), 1, f);
}







C_矩阵计算节点::C_矩阵计算节点(S_设备环境& ctx) : C_节点基类("矩阵计算节点") {
	f_setWName(u"矩阵计算");
	m_Ctx = ctx;

	C_插座基类* socket;
	DEF_创建Mat4X4_1D插座_I(u"矩阵A");
	DEF_创建Mat4X4_1D插座_I(u"矩阵B");
	//DEF_创建引用插座_I(u"引用数据");

	DEF_创建Mat4X4_1D插座_O(u"矩阵");


	m_计算方式 = f_alloc_EnumProp(nullptr,
		//	0				1				2				3				4
		{
			{u"*", u""}, {u"逆矩阵", u""}, {u"归一化", u""}, {u"直接相乘", u""},
			//	5			6			7				8			9			10
			//{u"+=", ""}, {u"-=", ""}, {u"*=", ""}, {u"/=", ""}, {u"%=", ""}, {u"点积", ""},
			//	11			12				13				14				15
			//{u"差集", ""}, {u"相交", ""}, {u"反射", ""}, {u"折射", ""}, {u"射线相交网格", ""} 
		},
		u"计算方式",
		0,
		nullptr
		);
	m_计算方式.m_私有 = true;

	m_是否改变原数据 = f_alloc_BoolProp(nullptr, u"是否改变原数据");
	m_是否改变原数据.m_私有 = true;

	m_执行代码 = f_alloc_BoolProp(nullptr, u"执行代码");
	m_执行代码.m_私有 = true;
}

C_矩阵计算节点::~C_矩阵计算节点() {
}

bool C_矩阵计算节点::f_update() {
	auto& inMat1 = *DEF_Mat44插座_1D数据(f_get输入插座(1), 0);
	auto& inMat2 = *DEF_Mat44插座_1D数据(f_get输入插座(2), 0);
	auto outMat = DEF_Mat44插座_1D数据(f_get输出插座(1), 0);

	uint32 num1 = inMat1.count;
	uint32 num2 = inMat2.count;
	if (!num1 || !num2) return true;

	num1 = DEF_Max(num1, num2);

	bool in1单例 = inMat1.count < num1;
	bool in2单例 = inMat2.count < num1;
	f_core_array_resize((S_Array*)outMat, num1);
	
	switch (f_prop_enum(m_计算方式)) {
	case 0: {
		for (uint32 i = 0; i < num1; ++i) {
			Mat44f* inMat_a;
			Mat44f inMat_b;

			if (in1单例) inMat_a = &inMat1.ptr_userData[0];
			else inMat_a = &inMat1.ptr_userData[i];

			if (in2单例) inMat_b = inMat2.ptr_userData[0];
			else inMat_b = inMat2.ptr_userData[i];
			
			outMat->ptr_userData[i] = (*inMat_a) * (inMat_b);
		}
		break;
	}
	case 1: {
		for (uint32 i = 0; i < num1; ++i) {
			//outMat->ptr_userData[i] = f_mat44_Inverse(inMat1.ptr_userData[i]);
			outMat->ptr_userData[i] = f_mat44_Invert(inMat1.ptr_userData[i]);
		}
		break;
	}
	case 2: {
		for (uint32 i = 0; i < num1; ++i) {
			outMat->ptr_userData[i] = inMat1.ptr_userData[i];
			mat44_normalize(outMat->ptr_userData[i]);
		}
		break;
	}
	}
	return false;
}

std::string C_矩阵计算节点::f_编译(C_节点基类* rn, std::string& 声明, std::vector<std::string>& 定义, std::string& 释放) {
	m_Code = "";
	m_ReleaseCode = "";

	C_插座基类* socket0 = f_get输入插座(1);
	C_插座基类* socket1 = f_get输入插座(2);

	if (!(socket0->f_isLink())) {
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 1, E_值类型::e_Type_Mat4X4);
	}
	if (!(socket1->f_isLink())) {
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 2, E_值类型::e_Type_Mat4X4);
	}


	//if (socket0->f_isLink()) {
		f_su_插座类型切换到连入的插座类型(this, E_插座方向::e_插座Type_输入, 1);

		std::string 新变量 = f_getName();

		bool 创建数组 = false;
		switch (socket0->m_Type) {
		case E_值类型::e_Type_Mat4X4:
			f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 2, E_值类型::e_Type_Mat4X4);
			f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 1, E_值类型::e_Type_Mat4X4);
			m_Code = "Mat44f " + 新变量 + ";\n";
			break;
		case E_值类型::e_Type_Mat4X4_1D: {
			f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 2, E_值类型::e_Type_Mat4X4_1D);
			f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 1, E_值类型::e_Type_Mat4X4_1D);
			m_Code = "S_Mat44Array* " + 新变量 + ";\n";
			创建数组 = true;
			break;
		}
		default:
			return "";
		}
		socket1 = f_get输入插座(2);


		m_Code += "{\n";

		m_Code += socket0->f_构建变量代码(0);
		m_Code += socket1->f_构建变量代码(0);

		if (创建数组) {
			m_Code += 新变量 + " = " + f_代码构建_创建Array(E_值类型::e_Type_Mat4X4_1D, f_代码构建_Array数组数量(socket0->f_getCode(0)));
			m_Code += "f_math_mat44_相乘m(" + socket0->f_getCode(0) + ", " + socket1->f_getCode(0) + ", " + 新变量 + ");\n";
		}
		else {
			m_Code += 新变量 + " = f_math_mat44_相乘(" + socket0->f_getCode(0) + ", " + socket1->f_getCode(0) + ");\n";
		}

		m_Code += m_ReleaseCode;
		m_Code += "}\n";

		f_get输出插座(1)->f_setCode(新变量);



		if (m_区域父节点) {
			m_区域父节点->m_Code += m_Code;

			if (创建数组) {
				m_区域父节点->m_ReleaseCode += f_代码构建_销毁数组(新变量);
			}
			return "";
		}
	//}
	//else {
	//	f_get输出插座(1)->f_setCode("");
	//}
	if (创建数组) {
		释放 += f_代码构建_销毁数组(新变量);
	}
	return m_Code;
}

void C_矩阵计算节点::f_读取(FILE* f) {
	C_节点基类::f_读取(f);
	auto 文件块 = f_file_读取文件块(f);

	if (文件块.m_块类型 == E_节点工程文件块类型::e_工程文件块_节点实例属性) {
		const uint8* 下一次读取数据指针 = 文件块.m_data;
		下一次读取数据指针 = f_prop_Load(m_计算方式, 下一次读取数据指针);
		下一次读取数据指针 = f_prop_Load(m_是否改变原数据, 下一次读取数据指针);
		下一次读取数据指针 = f_prop_Load(m_执行代码, 下一次读取数据指针);
	}
	free(文件块.m_data);
}

void C_矩阵计算节点::f_写入(FILE* f) {
	C_节点基类::f_写入(f);
	auto 文件块 = f_文件块_创建(E_节点工程文件块类型::e_工程文件块_节点实例属性, S_引擎配置::g_文件版本号);

	S_UI8Array* 块 = (S_UI8Array*)f_core_array_new(0, sizeof(uint8));
	f_prop_Save(m_计算方式, 块);
	f_prop_Save(m_是否改变原数据, 块);
	f_prop_Save(m_执行代码, 块);

	f_file_保存文件块(f, 文件块, 块);
}

C_节点基类* f_node_创建矩阵计算节点(S_设备环境& ctx, C_节点树* 子节点树) {
	return new C_矩阵计算节点(ctx);
}

C_节点基类* f_node_加载矩阵计算节点(S_设备环境& ctx, FILE* f) {
	C_矩阵计算节点* node = new C_矩阵计算节点(ctx);
	//fread(&(((S_PropValueEnum*)node->m_成员.m_Value)->m_当前选项), sizeof(uint8), 1, f);
	return node;
}

void f_node_保存矩阵计算节点(C_节点基类* n, FILE* f) {
	C_矩阵计算节点* node = dynamic_cast<C_矩阵计算节点*>(n);
	//fwrite(&(((S_PropValueEnum*)node->m_成员.m_Value)->m_当前选项), sizeof(uint8), 1, f);
}






C_矩阵转换节点::C_矩阵转换节点(S_设备环境& ctx) : C_节点基类(DEF_矩阵转换节点) {
	f_setWName(u"矩阵转换");
	m_Ctx = ctx;

	C_插座基类* socket;
	DEF_创建Mat4X4插座_I(u"矩阵");
	DEF_创建Mat4X4插座_O(u"新矩阵");


	m_转换类型 = f_alloc_EnumProp(nullptr, {
		{u"欧拉角"},
		{u"归一化"},
		{u"转置"},
		{u"逆"},
	}, u"转换类型");
	m_转换类型.m_私有 = true;
}

C_矩阵转换节点::~C_矩阵转换节点() {
	f_prop_Release(m_转换类型);
}

bool C_矩阵转换节点::f_update() {
	auto& 矩阵 = *DEF_Mat4X4插座数据(f_get输入插座(1));
	//auto& 新矩阵 = *DEF_Mat4X4插座数据(f_get输出插座(1));

	switch (f_prop_enum(m_转换类型)) {
	case 0:
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 1, E_值类型::e_Type_Vec3);
		//*DEF_Vec3插座数据(f_get输出插座(1), 0) = f_graph_旋转矩阵转欧拉角(f_mat3x3_T(f_mat44_to_33(矩阵)));
		DEF_Vec3插座数据(f_get输出插座(1)) = f_graph_旋转矩阵转欧拉角(f_mat44_to_33(矩阵));
		break;

	case 1:
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 1, E_值类型::e_Type_Mat4X4);
		*DEF_Mat4X4插座数据(f_get输出插座(1)) = 矩阵;
		mat44_normalize(*DEF_Mat4X4插座数据(f_get输出插座(1)));
		break;

	case 2:
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 1, E_值类型::e_Type_Mat4X4);
		*DEF_Mat4X4插座数据(f_get输出插座(1)) = f_mat44_T(矩阵);
		break;

	case 3:
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 1, E_值类型::e_Type_Mat4X4);
		//*DEF_Mat4X4插座数据(f_get输出插座(1)) = f_mat44_Inverse(矩阵);
		*DEF_Mat4X4插座数据(f_get输出插座(1)) = f_mat44_Invert(矩阵);
		break;
	default:
		break;
	}
	
	return false;
}

void C_矩阵转换节点::f_getStr(std::vector<std::vector<std::u16string>>& 文本) {
	auto socket1 = f_get输出插座(1);
	switch (socket1->m_Type) {
	case E_值类型::e_Type_Mat4X4: {
		break;
	}
	case E_值类型::e_Type_Vec3: {
		auto& v1 = DEF_Vec3插座数据(socket1);
		
		std::vector<std::u16string> 输出(4);
		输出[0] = u"旋转角度";
		输出[1] = u"x:" + f_浮点数值转宽字符串(v1.x);
		输出[2] = u"y:" + f_浮点数值转宽字符串(v1.y);
		输出[3] = u"z:" + f_浮点数值转宽字符串(v1.z);

		文本.push_back(输出);
		break;
	}
	}
}

void C_矩阵转换节点::f_读取(FILE* f) {
	C_节点基类::f_读取(f);
	f_prop_Load(m_转换类型, f);
}

void C_矩阵转换节点::f_写入(FILE* f) {
	C_节点基类::f_写入(f);
	f_prop_Save(m_转换类型, f);
}

C_节点基类* f_node_创建旋转矩阵转欧拉角节点(S_设备环境& ctx, C_节点树* 子节点树) {
	return new C_矩阵转换节点(ctx);
}

C_节点基类* f_node_加载旋转矩阵转欧拉角节点(S_设备环境& ctx, FILE* f) {
	C_矩阵转换节点* node = new C_矩阵转换节点(ctx);
	return node;
}

void f_node_保存旋转矩阵转欧拉角节点(C_节点基类* n, FILE* f) {
	C_矩阵转换节点* node = dynamic_cast<C_矩阵转换节点*>(n);
}









C_顶点变换节点::C_顶点变换节点(S_设备环境& ctx) : C_节点基类(DEF_顶点变换节点) {
	f_setWName(u"顶点变换");
	m_Ctx = ctx;

	C_插座基类* socket;
	DEF_创建Vec3插座_I(u"点", nullptr);
	DEF_创建Vec3插座_I(u"移动", nullptr);
	DEF_创建Vec3插座_I(u"旋转", nullptr);
	DEF_创建Vec3插座_I(u"缩放", nullptr);

	DEF_创建Vec3插座_O(u"点");

	DEF_Vec3插座数据(f_get输入插座(4)) = {1,1,1};
}

C_顶点变换节点::~C_顶点变换节点() {
}

bool C_顶点变换节点::f_update() {
	
	return false;
}

std::string C_顶点变换节点::DEF_节点编译函数 {
	m_ReleaseCode = "";
	m_Code = "";
	std::string name = f_getName();

	auto* socket1 = f_get输入插座(1);
	auto* socket2 = f_get输入插座(2);
	auto* socket3 = f_get输入插座(3);
	auto* socket4 = f_get输入插座(4);
	bool 创建数组 = false;

	创建数组 |= socket1->f_get接入的数据类型() == E_值类型::e_Type_Vec3_1D;
	创建数组 |= socket2->f_get接入的数据类型() == E_值类型::e_Type_Vec3_1D;
	创建数组 |= socket3->f_get接入的数据类型() == E_值类型::e_Type_Vec3_1D;
	创建数组 |= socket4->f_get接入的数据类型() == E_值类型::e_Type_Vec3_1D;

	if (!socket1->f_isLink() && !socket2->f_isLink() && !socket3->f_isLink() && !socket4->f_isLink()) {
		创建数组 = false;
	}

	if (创建数组) {
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 1, E_值类型::e_Type_Vec3_1D);
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 2, E_值类型::e_Type_Vec3_1D);
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 3, E_值类型::e_Type_Vec3_1D);
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 4, E_值类型::e_Type_Vec3_1D);
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 1, E_值类型::e_Type_Vec3_1D);

		m_Code = DEF_S(S_Vec3Array*)" " + name + ";\n";
	}
	else {
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 1, E_值类型::e_Type_Vec3);
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 2, E_值类型::e_Type_Vec3);
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 3, E_值类型::e_Type_Vec3);
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 4, E_值类型::e_Type_Vec3);
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 1, E_值类型::e_Type_Vec3);

		m_Code = DEF_S(vec3)" " + name + ";\n";

		DEF_Vec3插座数据(f_get输入插座(3)) = {1,1,1};
	}
	socket1 = f_get输入插座(1);
	socket2 = f_get输入插座(2);
	socket3 = f_get输入插座(3);
	socket4 = f_get输入插座(4);


	m_Code += "{\n";

	m_Code += socket1->f_构建变量代码(0);
	m_Code += socket2->f_构建变量代码(0);
	m_Code += socket3->f_构建变量代码(0);
	m_Code += socket4->f_构建变量代码(0);
	if (创建数组) {
		m_Code += name + " = " + f_代码构建_创建Array(E_值类型::e_Type_Vec3_1D, "1");
		m_Code += DEF_S(f_JIT_坐标变换m)"(" + socket1->f_getCode(0) + ", " + socket2->f_getCode(0) + ", " + socket3->f_getCode(0) + ", " + socket4->f_getCode(0) + ", " + name + ");\n";
	}
	else {
		m_Code += name + " = " + DEF_S(f_JIT_坐标变换)"(" + socket1->f_getCode(0) + ", " + socket2->f_getCode(0) + ", " + socket3->f_getCode(0) + ", " + socket4->f_getCode(0) + ");\n"; 
	}

	m_Code += m_ReleaseCode;
	m_Code += "}\n";


	f_get输出插座(1)->f_setCode(name);
	if (m_区域父节点) {
		(*m_区域父节点).m_Code += m_Code;
		if (创建数组) {
			m_区域父节点->m_ReleaseCode += f_代码构建_销毁数组(name);
		}
		return "";
	}
	if (创建数组) {
		释放 += f_代码构建_销毁数组(name);
	}
	return m_Code;
}

void C_顶点变换节点::f_Copy(const C_节点基类* node) {
	C_节点基类::f_Copy(node);

	auto* socket2 = f_get输入插座(2);
	auto* socket3 = f_get输入插座(3);
	auto* socket4 = f_get输入插座(4);

	socket2->f_Copy(node->f_get输入插座(2));
	socket3->f_Copy(node->f_get输入插座(3));
	socket4->f_Copy(node->f_get输入插座(4));
}

C_节点基类* f_node_创建顶点变换节点(S_设备环境& ctx, C_节点树* 子节点树) {
	return new C_顶点变换节点(ctx);
}

C_节点基类* f_node_加载顶点变换节点(S_设备环境& ctx, FILE* f) {
	C_顶点变换节点* node = new C_顶点变换节点(ctx);
	return node;
}

void f_node_保存顶点变换节点(C_节点基类* n, FILE* f) {
	C_顶点变换节点* node = dynamic_cast<C_顶点变换节点*>(n);
}


